package lib.quasar.db.manager;


import android.annotation.SuppressLint;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import org.greenrobot.greendao.query.QueryBuilder;

import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import lib.quasar.context.BaseApp;
import lib.quasar.db.gen.AerainfoDao;
import lib.quasar.db.gen.ChatDao;
import lib.quasar.db.gen.DaoMaster;
import lib.quasar.db.gen.DaoSession;
import lib.quasar.db.gen.DiagnoseinfoDao;
import lib.quasar.db.gen.HospitalDao;
import lib.quasar.db.gen.HttpDao;
import lib.quasar.db.gen.MedicineDao;
import lib.quasar.db.gen.MessageDao;
import lib.quasar.db.gen.PedometerDao;
import lib.quasar.db.gen.UserDao;
import lib.quasar.db.helper.DbUpdataHelper;
import lib.quasar.db.table.Aerainfo;
import lib.quasar.db.table.Chat;
import lib.quasar.db.table.Diagnoseinfo;
import lib.quasar.db.table.Hospital;
import lib.quasar.db.table.Http;
import lib.quasar.db.table.Medicine;
import lib.quasar.db.table.Message;
import lib.quasar.db.table.User;
import lib.quasar.util.DateUtil;

/**
 * description: 实体类管理
 * created by kalu on 2018/4/16 20:54
 */
public final class DBManager {

    public static final String DB_NAME = "quasar_patient.db";
    // public static final String DB_PASSWORD = "11030031";

    private static Long patientId;

    /*************************************   创建单例   *********************************************/

    private DaoMaster mDaoMaster;

    private static class SingletonHolder {
        private final static DBManager instance = new DBManager();
    }

    public static DBManager getInstance() {
        return SingletonHolder.instance;
    }

    private DBManager() {

        final DBContextWrapper dbContextWrapper = new DBContextWrapper(BaseApp.getContext());
        // final DbUpdataHelper mHelper = new DbUpdataHelper(dbContextWrapper, DBManager.DB_NAME, null);
        final DbUpdataHelper mHelper = new DbUpdataHelper(dbContextWrapper, DBManager.DB_NAME, null);

        // final Database db = mHelper.getEncryptedWritableDb(DBManager.DB_PASSWORD);// 数据库加密
        final SQLiteDatabase db = mHelper.getReadableDatabase();// 数据库不加密;
        mDaoMaster = new DaoMaster(db);
    }

    /*********************************************************************/

    public List<Medicine> getMedicineList() {
        List<Medicine> modelList = mDaoMaster.newSession().getMedicineDao().queryBuilder().list();
        return modelList;
    }

    public List<Medicine> getMedicineList(String name) {
        List<Medicine> modelList = mDaoMaster.newSession().getMedicineDao().queryBuilder().where(MedicineDao.Properties.Name.eq(name)).list();
        return modelList;
    }

    public Medicine getMedicine(String name, String unit) {
        List<Medicine> modelList = mDaoMaster.newSession().getMedicineDao().queryBuilder().where(MedicineDao.Properties.Name.eq(name), MedicineDao.Properties.Dose.eq(unit)).list();
        if (null == modelList || modelList.size() == 0) return null;
        else return modelList.get(0);
    }

    /*********************************************************************/

    public PedometerDao getPedometerDao() {
        return mDaoMaster.newSession().getPedometerDao();
    }

    /*********************************************************************/

    @SuppressLint("CheckResult")
    public void asynGetUserModel(OnDbChangeListener<User> listener) {

        Observable.create((ObservableOnSubscribe<User>) e -> {

            final User user = syncGetUserModel();
            e.onNext(user);

        }).subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        patient -> listener.onSucc(patient),
                        throwable -> listener.onFail());
    }

    public User syncGetUserModel() {

        final DaoSession daoSession = mDaoMaster.newSession();
        final UserDao patientDao = daoSession.getUserDao();
        final List<User> list = patientDao.queryBuilder().list();

        if (null == list || list.size() == 0) {
            final User user = new User();
            patientDao.insert(user);
            return user;
        } else if (list.size() > 1) {
            final User user = list.get(list.size() - 1);
            daoSession.clear();
            patientDao.insert(user);
            return user;
        } else {
            final User user = list.get(0);
            return user;
        }
    }

    public void resetUserModel() {
        final UserDao patientDao = mDaoMaster.newSession().getUserDao();
        final List<User> list = patientDao.queryBuilder().list();
        if (list.size() == 0) {
            final User patient = new User();
            patient.reset();
            patientDao.insert(patient);
        } else {
            final User patient = list.get(0);
            patient.reset();
            updataUserModel(patient);
        }
    }

    public void setUserModel(User news) {
        final User olds = syncGetUserModel();
        olds.updateInfo(news);
        updataUserModel(olds);
    }

    public void updataUserModel(User patient) {
        mDaoMaster.newSession().getUserDao().update(patient);
    }

    /**
     * private Long doctorid = 0L;
     * private String clientid;
     * private String icon;
     * private String real_name;
     * private String birthday;
     * private String phone;
     * <p>
     * private Integer age = -1;
     * private Integer sex = -1;
     *
     * @param patirntid
     * @param icon
     * @param phone
     */
    public void updataUserModel(Long patirntid, String icon, String phone) {
        final User user = syncGetUserModel();
        user.setIcon(icon);
        user.setPatientid(patirntid);
        user.setPhone(phone);
        updataUserModel(user);
    }

    public void updataUserModel(Long patientid, String icon, String phone, String real_name, String birthday, String hospital, String age, Integer sex) {
        final User user = syncGetUserModel();
        user.setIcon(icon);
        user.setPatientid(patientid);
        user.setPhone(phone);
        user.setReal_name(real_name);
        user.setBirthday(birthday);
        user.setHospital_name(hospital);
        user.setAge(age);
        user.setSex(sex);
        updataUserModel(user);
    }

    public void updataUserClientId(String clientid) {
        final User UserModel = syncGetUserModel();
        UserModel.setClientid(clientid);
        updataUserModel(UserModel);
    }

    public void updataUserGuide(boolean needGuide) {
        final User UserModel = syncGetUserModel();
        UserModel.setPatientid(needGuide ? null : 0L);
        updataUserModel(UserModel);
    }

    /***********************************************************************************************/

    public List<Http> getHttplList() {
        List<Http> modelList = mDaoMaster.newSession().getHttpDao().queryBuilder().list();
        return modelList;
    }

    public List<Http> getHttplList(String url) {
        List<Http> modelList = mDaoMaster.newSession().getHttpDao().queryBuilder().where(HttpDao.Properties.Url.eq(url)).list();
        return modelList;
    }

    public void updataHttpModel(int index, Http model) {
        mDaoMaster.newSession().getHttpDao().update(model);
    }

    /******************************************************************************/

    public List<Aerainfo> getProvinceList() {
        List<Aerainfo> list = mDaoMaster.newSession().getAerainfoDao().queryBuilder().where(AerainfoDao.Properties.PatientID.eq("1")).list();
        return list;
    }

    public List<Aerainfo> getCityList(String areaCode) {
        List<Aerainfo> list = mDaoMaster.newSession().getAerainfoDao().queryBuilder().where(AerainfoDao.Properties.PatientID.eq(areaCode)).list();
        return list;
    }

    public List<Aerainfo> getPrefectureList(String areaCode) {
        List<Aerainfo> list = mDaoMaster.newSession().getAerainfoDao().queryBuilder().where(AerainfoDao.Properties.PatientID.eq(areaCode)).list();
        return list;
    }

    public String getAreaCode(String areaname) {
        String code = mDaoMaster.newSession().getAerainfoDao().queryBuilder().where(AerainfoDao.Properties.AeraInfoName.eq(areaname)).list().get(0).getAeraInfoID();
        return code;
    }

    public List<Aerainfo> getAreaList(String areaCode) {
        List<Aerainfo> list = mDaoMaster.newSession().getAerainfoDao().queryBuilder().where(AerainfoDao.Properties.PatientID.eq(areaCode)).list();
        return list;
    }

    public String getCityCode(String cityName) {
        String code = mDaoMaster.newSession().getAerainfoDao().queryBuilder().where(AerainfoDao.Properties.AeraInfoName.eq(cityName)).list().get(0).getAeraInfoID();
        return code;
    }

    public List<Hospital> getHospitalList(String aeraCode) {
        List<Hospital> list = mDaoMaster.newSession().getHospitalDao().queryBuilder().where(HospitalDao.Properties.Provinceid.eq(aeraCode)).list();
        return list;
    }

    public String getHospitalId(String hospitalName) {
        Hospital model = mDaoMaster.newSession().getHospitalDao().queryBuilder().where(HospitalDao.Properties.Name.eq(hospitalName)).list().get(0);
        return model.getId();
    }

    /************************************************/

    public List<Diagnoseinfo> getDiagnoseList(int type) {
        List<Diagnoseinfo> list = mDaoMaster.newSession().getDiagnoseinfoDao().queryBuilder().where(DiagnoseinfoDao.Properties.Message_type.eq(type)).list();
        return list;
    }

    /************************************************/

    public List<Chat> getChatList() {
        List<Chat> list = mDaoMaster.newSession().getChatDao().queryBuilder().list();
        return list;
    }

    public List<Chat> getChatList(Long myselfid, Long otherid) {
        // Log.e("DBManager", "getChatList ==> myselfid = " + myselfid + ", otherid = " + otherid);

        final QueryBuilder<Chat> chatQueryBuilder = mDaoMaster.newSession().getChatDao().queryBuilder();
        // 自己发, 别人收, 别人发, 自己收
        chatQueryBuilder.where(ChatDao.Properties.Sendid.in(myselfid, otherid), ChatDao.Properties.Receiveid.in(otherid, myselfid));
        return chatQueryBuilder.list();
    }

    public void insertChat(Chat messgaeModel) {

        if (null != messgaeModel) {
            mDaoMaster.newSession().getChatDao().insert(messgaeModel);
        }
        updateMessage(messgaeModel);
    }

    public void updateChatSucc(Long sendid, Long receiveid, Long sendtimestamp) {

        final QueryBuilder<Chat> chatQueryBuilder = mDaoMaster.newSession().getChatDao().queryBuilder();
        // 自己发, 别人收, 别人发, 自己收
        chatQueryBuilder.where(ChatDao.Properties.Sendid.eq(sendid), ChatDao.Properties.Receiveid.eq(receiveid), ChatDao.Properties.Send_timestamp.eq(sendtimestamp));
        final List<Chat> list = chatQueryBuilder.list();

        if (null != list && list.size() > 0) {
            final Chat chat = list.get(0);
            chat.setSendSucc();
            mDaoMaster.newSession().getChatDao().update(chat);
        }
    }

    /************************************************/

    public final List<Message> getMessageList(Long messageOwn) {
        List<Message> list = mDaoMaster.newSession().getMessageDao().queryBuilder().where(MessageDao.Properties.Message_own.eq(messageOwn)).list();
        // Log.e("DBManager", "getMessageList ==> size = " + list.size() + " , doctorid = " + doctorid);

        return list;
    }

    private final void updateMessage(Chat chat) {
        // Log.e("DBManager", "updateMessage[chat] ==> " + chat.toString());

        if (null == patientId) {
            final User user = syncGetUserModel();
            patientId = user.getPatientid();
        }

        final boolean isOwn = chat.isOwn(patientId);
        final Long messageId = isOwn ? chat.getReceiveid() : chat.getSendid();

        final Message message;
        List<Message> list = mDaoMaster.newSession().getMessageDao().queryBuilder().where(MessageDao.Properties.Message_id.eq(messageId)).list();
        if (null == list || list.isEmpty()) {
            message = new Message();
            // Log.e("DBManager", "updateMessage[message0] ==> 创建");
        } else {
            // Log.e("DBManager", "updateMessage[message0] ==> 查找");
            message = list.get(0);
        }
        // Log.e("DBManager", "updateMessage[message1] ==> " + message.toString());

        if (!isOwn) {
            message.setMessage_icon(chat.getSend_icon());
        }
        message.setMessage_id(messageId);
        message.setMessage_own(patientId);
        message.setMessage_time(DateUtil.formatDate(chat.getSend_timestamp()));
        message.setMessage_num(isOwn ? message.getMessage_num() : message.getMessage_num() + 1);
        message.setMessage_name(isOwn ? chat.getReceive_name() : chat.getSend_name());
        // 图片
        if (Chat.PICTURE.equals(chat.getMessage_type())) {
            message.setMessage_text("[图片]");
        }
        // 化验单
        else if (Chat.INSPECTION.equals(chat.getMessage_type())) {
            message.setMessage_text("[化验单]");
        }
        // 诊断
        else if (Chat.DIAGNOSE.equals(chat.getMessage_type())) {
            message.setMessage_text("[诊断]");
        }
        // 化验单
        else if (Chat.INSPECTION.equals(chat.getMessage_type())) {
            message.setMessage_text("[化验单]");
        }
        // 药单
        else if (Chat.PRESCRIPTION.equals(chat.getMessage_type())) {
            message.setMessage_text("[药单消息]");
        }
        // 文字消息
        else {
            message.setMessage_text(chat.getMessage());
        }
        // Log.e("DBManager", "updateMessage[message2] ==> " + message.toString());

        if (null == message.getId_() || message.getId_().equals(0f) || message.getId_().equals(0)) {
            mDaoMaster.newSession().getMessageDao().insert(message);
        } else {
            mDaoMaster.newSession().getMessageDao().update(message);
        }
        // Log.e("DBManager", "updateMessage[message3] ==> " + message.toString());
    }

    public final void clearMessage(Long messageId) {
        Log.e("DBManager", "clearMessage ==> messageId = " + messageId);

        List<Message> list = mDaoMaster.newSession().getMessageDao().queryBuilder().where(MessageDao.Properties.Message_id.eq(messageId)).list();
        if (null != list && list.size() > 0) {
            final Message message = list.get(0);
            message.setMessage_num(0);
            mDaoMaster.newSession().getMessageDao().update(message);
            Log.e("DBManager", "clearMessage ==> " + message.toString());
        }
    }

    public final Message getMessage(Long messageId) {
        Log.e("DBManager", "clearMessage ==> messageId = " + messageId);

        List<Message> list = mDaoMaster.newSession().getMessageDao().queryBuilder().where(MessageDao.Properties.Message_id.eq(messageId)).list();
        if (null != list && list.size() > 0) {
            final Message message = list.get(0);
            return message;
        }
        return null;
    }

    /************************************************/

    public interface OnDbChangeListener<T> {

        void onFail();

        void onSucc(T result);
    }
}